package com.terrier.ui.controls.scrollClasses
{
    import com.terrier.ui.controls.WxButton;
    import com.terrier.ui.controls.WxButtonPhase;
    import com.terrier.ui.controls.supportClasses.WxTrackBase;
    import com.terrier.ui.events.WxButtonEvent;
    import com.terrier.ui.skins.IWxScrollBarSkin;
    import com.terrier.ui.skins.IWxSkinBase;
    import com.terrier.ui.skins.WxSkinManager;

    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.geom.Point;
    import flash.utils.Timer;

    /**
     * 滚动条基类. 它是水平滚动条和垂直滚动条的基类
     * @author Jarvis.weng
     */
    public class WxScrollBarBase extends WxTrackBase
    {
        /**
         * @private
         */
        protected var increaseButton:WxButton;

        /**
         * @private
         */
        protected var decreaseButton:WxButton;

        private var _trackScrollTimer:Timer;

        private var _lineScrollTimer:Timer;

        private var _repeatDelay:Number = 500;

        private var _repeatInterval:Number = 50;

        private var _increase:Boolean;

        private var _pageSize:Number = 0;

        /**
         * 构造函数
         */
        public function WxScrollBarBase()
        {
            super();
        }

        /**
         * 调用 changeValueByPage() 方法时 value 属性的更改值。
         */
        public function get pageSize():Number
        {
            return _pageSize;
        }

        /**
         * @private
         */
        public function set pageSize(value:Number):void
        {
            if (value == _pageSize)
            {
                return;
            }

            _pageSize = value;

            updateView();
        }

        /**
         * @private
         */
        override public function setSkin(value:IWxSkinBase):void
        {
            super.setSkin(value);

            if (skin != null)
            {
                increaseButton.setSkin(skin.increaseButtonSkin);
                decreaseButton.setSkin(skin.decreaseButtonSkin);
            }
            else
            {
                increaseButton.setSkin(null);
                decreaseButton.setSkin(null);
            }

            invalidateView();
        }

        /**
         * @private
         */
        override public function set enabled(value:Boolean):void
        {
            super.enabled = value;
            increaseButton.enabled = value;
            decreaseButton.enabled = value;
        }

        /**
         * @private
         */
        override protected function initialize():void
        {
            super.initialize();

            if (increaseButton == null)
            {
                increaseButton = new WxButton();
                addChild(increaseButton);
                increaseButton.addEventListener(WxButtonEvent.BUTTON_PRESS, buttonPressHandler)
            }

            if (decreaseButton == null)
            {
                decreaseButton = new WxButton();
                addChild(decreaseButton);
                decreaseButton.addEventListener(WxButtonEvent.BUTTON_PRESS, buttonPressHandler);
            }

            track.addEventListener(WxButtonEvent.BUTTON_PRESS, trackPressHandler);
        }

        //--------------------------------------------------
        //
        // Event Listeners
        //
        //--------------------------------------------------

        private function buttonPressHandler(e:WxButtonEvent):void
        {
            var btn:WxButton = WxButton(e.currentTarget);
            btn.addEventListener(WxButtonEvent.BUTTON_RELEASE, buttonReleaseHandler);
            btn.addEventListener(WxButtonEvent.BUTTON_PHASE_CHANGE, buttonPhaseChangeHandler);

            _increase = (btn == increaseButton);

            changeValueByStep(_increase);

            if (_lineScrollTimer == null)
            {
                _lineScrollTimer = new Timer(0, 1);
            }
            _lineScrollTimer.delay = _repeatDelay;
            _lineScrollTimer.repeatCount = 1;
            _lineScrollTimer.addEventListener(TimerEvent.TIMER, lineScrollTimerHandler);
            _lineScrollTimer.start();
        }

        private function buttonPhaseChangeHandler(e:WxButtonEvent):void
        {
            if (_lineScrollTimer != null)
            {
                e.currentPhase == WxButtonPhase.DOWN ? _lineScrollTimer.start() : _lineScrollTimer.stop();
            }
        }

        private function buttonReleaseHandler(e:WxButtonEvent):void
        {
            var btn:WxButton = WxButton(e.currentTarget);
            btn.removeEventListener(WxButtonEvent.BUTTON_RELEASE, buttonReleaseHandler);
            btn.removeEventListener(WxButtonEvent.BUTTON_PHASE_CHANGE, buttonPhaseChangeHandler);

            if (_lineScrollTimer != null)
            {
                _lineScrollTimer.stop();
                _lineScrollTimer.removeEventListener(TimerEvent.TIMER, lineScrollTimerHandler);
                _lineScrollTimer = null;
            }
        }

        private function lineScrollTimerHandler(e:TimerEvent):void
        {
            changeValueByStep(_increase);

            if (_lineScrollTimer.repeatCount == 1)
            {
                _lineScrollTimer.delay = _repeatInterval;
                _lineScrollTimer.repeatCount = 0;
            }
        }

        private function trackPressHandler(e:WxButtonEvent):void
        {
            var btn:WxButton = WxButton(e.currentTarget);
            btn.addEventListener(WxButtonEvent.BUTTON_RELEASE, trackReleaseHandler);
            btn.addEventListener(WxButtonEvent.BUTTON_PHASE_CHANGE, trackPhaseChangeHandler);

            var pt:Point = new Point(track.mouseX, track.mouseY);
            var newValue:Number = pointToValue(pt);

            _increase = newValue > value

            changeValueByPage(_increase);

            if (_trackScrollTimer == null)
            {
                _trackScrollTimer = new Timer(0, 1);
            }
            _trackScrollTimer.delay = _repeatDelay;
            _trackScrollTimer.repeatCount = 1;
            _trackScrollTimer.addEventListener(TimerEvent.TIMER, trackScrollTimerHandler);
            _trackScrollTimer.start();
        }

        private function trackPhaseChangeHandler(e:WxButtonEvent):void
        {
            if (_trackScrollTimer != null)
            {
                e.currentPhase == WxButtonPhase.DOWN ? _trackScrollTimer.start() : _trackScrollTimer.stop();
            }
        }

        private function trackReleaseHandler(e:WxButtonEvent):void
        {
            var btn:WxButton = WxButton(e.currentTarget);
            btn.removeEventListener(WxButtonEvent.BUTTON_RELEASE, trackReleaseHandler);
            btn.removeEventListener(WxButtonEvent.BUTTON_PHASE_CHANGE, trackPhaseChangeHandler);

            if (_trackScrollTimer != null)
            {
                _trackScrollTimer.stop();
                _trackScrollTimer.removeEventListener(TimerEvent.TIMER, trackScrollTimerHandler);
                _trackScrollTimer = null;
            }
        }

        private function trackScrollTimerHandler(e:TimerEvent):void
        {
            if (_trackScrollTimer.repeatCount == 1)
            {
                _trackScrollTimer.delay = _repeatInterval;
                _trackScrollTimer.repeatCount = 0;
            }

            var pt:Point = new Point(track.mouseX, track.mouseY);
            var newValue:Number = pointToValue(pt);

            if (_increase && newValue < value + pageSize)
            {
                return;
            }
            else if (!_increase && newValue > value)
            {
                return;
            }

            changeValueByPage(_increase);
        }

        private function changeValueByPage(increase:Boolean):void
        {
            if (increase)
            {
                value += pageSize;
            }
            else
            {
                value -= pageSize;
            }
        }

        private function get skin():IWxScrollBarSkin
        {
            return _skin as IWxScrollBarSkin;
        }
    }
}
